from flask import Flask, jsonify, request, send_from_directory, make_response, send_file
from flask_cors import CORS
import yaml
import json
from datetime import datetime, timedelta
import threading
import time
import os
import logging
import traceback
from functools import wraps

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger('health_bed_app')

# 导入我们的模块
from device_connector import DeviceConnector, MockDeviceConnector
from real_device_connector import AliyunIoTConnector
from improved_aliyun_connector import ImprovedAliyunIoTConnector
from aliyun_config import aliyun_config
from data_processor import process_device_data, format_data_for_display, validate_bed_data
from auto_control_service import auto_control_service

app = Flask(__name__)
CORS(app)  # 允许跨域请求

# 全局变量存储最新数据
latest_data = {}
data_cache = {
    'current_data': {},  # 缓存最近一次的current-data响应
    'cache_time': None,    # 缓存时间
    'property_model_data': {  # 存储物模型数据
        'radar_heartrate': None,  # 心率
        'radar_breath': None,     # 呼吸
        'temp': None,             # 温度 
        'humidity': None          # 湿度
    },
    'last_update_time': None,     # 上次更新时间
    'data_source': 'unknown'      # 数据来源
}
device_connectors = {}
data_history = []  # 存储历史数据
is_running = False
api_response_times = []  # 存储API响应时间
startup_time = time.time()  # 记录启动时间

# 导入SQLite模块，用于持久化存储
import sqlite3
from contextlib import closing
import traceback

# 数据库文件路径
DB_PATH = 'health_bed_data.db'

# 初始化数据库
def init_database():
    try:
        # 如果数据库文件已存在，先尝试备份
        if os.path.exists(DB_PATH):
            backup_path = f"{DB_PATH}.bak"
            try:
                import shutil
                shutil.copy2(DB_PATH, backup_path)
                logger.info(f"✅ 已备份旧数据库到 {backup_path}")
            except Exception as e:
                logger.warning(f"⚠️ 备份数据库失败: {e}")
        
        with closing(sqlite3.connect(DB_PATH)) as conn:
            cursor = conn.cursor()
            
            # 删除旧表（如果存在），重新创建
            cursor.execute('DROP TABLE IF EXISTS property_model_data')
            
            # 创建物模型数据表（增加了数据有效性标志和数值字段）
            cursor.execute('''
            CREATE TABLE IF NOT EXISTS property_model_data (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp TEXT NOT NULL,               -- 记录时间
                identifier TEXT NOT NULL,              -- 字段标识符
                value TEXT,                            -- 原始值（字符串）
                numeric_value REAL,                    -- 数值（如果可转换）
                data_type TEXT,                        -- 数据类型
                name TEXT,                             -- 字段名称
                time TEXT,                             -- 设备上报时间
                is_valid INTEGER DEFAULT 1,            -- 数据是否有效
                device_id TEXT DEFAULT 'device1',      -- 设备ID（默认Spark设备）
                data_quality INTEGER DEFAULT 100       -- 数据质量评分（0-100）
            )
            ''')
            
            # 创建索引加速查询
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_property_timestamp ON property_model_data(timestamp)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_property_identifier ON property_model_data(identifier)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_property_device_id ON property_model_data(device_id)')
            
            conn.commit()
            logger.info("✅ 数据库初始化成功")
    except Exception as e:
        logger.error(f"❌ 数据库初始化失败: {e}")
        logger.error(traceback.format_exc())

# 性能监控装饰器
def monitor_performance(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        start_time = time.time()
        result = f(*args, **kwargs)
        end_time = time.time()
        execution_time = (end_time - start_time) * 1000  # 转换为毫秒
        
        # 记录API响应时间
        api_response_times.append({
            'endpoint': request.path,
            'method': request.method,
            'time_ms': execution_time,
            'timestamp': datetime.now().isoformat()
        })
        
        # 保持记录在合理范围内（最近100条）
        if len(api_response_times) > 100:
            api_response_times.pop(0)
            
        # 如果响应时间过长，记录警告日志
        if execution_time > 500:  # 500毫秒以上视为慢响应
            logger.warning(f"慢响应 - {request.path} ({request.method}): {execution_time:.2f}ms")
            
        return result
    return decorated_function

def load_config():
    """加载配置文件"""
    try:
        config_path = os.path.join(os.path.dirname(__file__), 'config', 'devices.yaml')
        with open(config_path, 'r', encoding='utf-8') as file:
            logger.info("配置文件加载成功")
            return yaml.safe_load(file)
    except Exception as e:
        logger.error(f"配置文件加载失败: {e}")
        # 返回默认配置
        return {
            'devices': {
                'device1': {
                    'name': '模拟设备1',
                    'url': 'mock://device1',
                    'token': 'mock_token_1',
                    'type': 'health_monitor'
                },
                'device2': {
                    'name': '模拟设备2', 
                    'url': 'mock://device2',
                    'token': 'mock_token_2',
                    'type': 'bed_controller'
                }
            },
            'system': {
                'update_interval': 5,
                'retry_attempts': 3,
                'timeout': 3,
                'cache_ttl': 2  # 缓存有效期（秒）
            }
        }

def initialize_devices(config):
    """初始化设备连接器"""
    global device_connectors
    
    devices_config = config.get('devices', {})
    successful_count = 0
    
    for device_id, device_config in devices_config.items():
        try:
            # 检查设备类型
            if device_config.get('url', '').startswith('mock://'):
                # 模拟设备
                connector = MockDeviceConnector(device_config)
            elif device_config.get('type') == 'aliyun_iot':
                # 真实阿里云IoT设备 - 使用改进的连接器
                connector = ImprovedAliyunIoTConnector(device_id)
            else:
                # 其他设备
                connector = DeviceConnector(device_config)
            
            device_connectors[device_id] = connector
            logger.info(f"设备 {device_id} ({device_config.get('name')}) 初始化成功")
            successful_count += 1
            
        except Exception as e:
            logger.error(f"设备 {device_id} 初始化失败: {e}")
    
    return successful_count

def data_collection_loop(update_interval, config):
    """数据收集循环"""
    global latest_data, data_history, is_running, data_cache
    
    retry_count = 0
    max_retries = config.get('system', {}).get('retry_attempts', 3)
    cache_ttl = config.get('system', {}).get('cache_ttl', 2)
    
    logger.info(f"🔥 数据收集循环开始运行！设备数量: {len(device_connectors)}")
    
    while is_running:
        try:
            current_time = datetime.now()
            new_data_received = False
            
            logger.info(f"🔄 数据收集循环开始新一轮，时间: {current_time.strftime('%H:%M:%S')}")
            
            for device_id, connector in device_connectors.items():
                try:
                    logger.info(f"🔗 开始从设备 {device_id} 获取数据，连接器: {connector.__class__.__name__}")
                    # 获取原始数据
                    raw_data = connector.fetch_data()
                    logger.info(f"📦 设备 {device_id} 获取数据结果: {'有数据' if raw_data else '无数据'}")
                    
                    if raw_data:
                        # 立即处理物模型数据（在process_device_data之前）
                        if device_id == 'device1':
                            logger.info(f"🔍 Device1原始数据完整内容: {raw_data}")
                            logger.info(f"原始数据类型: {type(raw_data)}, 是否有Data字段: {'Data' in raw_data if isinstance(raw_data, dict) else 'not dict'}")
                            logger.info(f"这是device1，开始提取物模型数据...")
                            property_info_list = raw_data.get('Data', {}).get('List', {}).get('PropertyStatusInfo', [])
                            logger.info(f"提取到的property_info_list: {len(property_info_list) if property_info_list else 0} 项")
                            if property_info_list:
                                logger.info(f"保存 {len(property_info_list)} 个物模型数据到数据库")
                                save_property_model_data(property_info_list)
                            else:
                                logger.warning(f"property_info_list为空或None")
                        
                        # 立即检查sitting_up状态并执行自动控制
                        if isinstance(raw_data, dict) and 'Data' in raw_data:
                            property_list = raw_data.get('Data', {}).get('List', {}).get('PropertyStatusInfo', [])
                            for prop in property_list:
                                if prop.get('Identifier') == 'sitting_up' and 'Value' in prop:
                                    sitting_up_value = int(prop['Value'])
                                    logger.info(f"🔍 检测到sitting_up状态: {sitting_up_value}")
                                    if sitting_up_value == 1:
                                        logger.info(f"🚨 检测到用户起身！立即执行床板抬起操作")
                                        try:
                                            # 直接调用自动控制逻辑
                                            auto_control_service.handle_sitting_up_detected(device_id)
                                        except Exception as control_error:
                                            logger.error(f"❌ 自动控制执行失败: {control_error}")
                                    break
                        
                        # 继续常规数据处理流程
                        processed_data = process_device_data(raw_data, connector.name)
                        
                        if processed_data:
                            # 格式化显示数据
                            display_data = format_data_for_display(processed_data)
                            
                            # 更新最新数据
                            latest_data[device_id] = display_data
                            new_data_received = True
                            
                            # 添加到历史记录
                            history_entry = {
                                'device_id': device_id,
                                'timestamp': current_time.isoformat(),
                                'data': display_data
                            }
                            data_history.append(history_entry)
                            
                            # 更新自动控制服务中的设备状态（保留原有逻辑）
                            auto_control_service.update_device_status(device_id, processed_data)
                            
                            # 每小时自动清理一次旧数据
                            current_hour = datetime.now().hour
                            if current_hour % 1 == 0 and datetime.now().minute < 5:
                                cleanup_old_data()
                except Exception as e:
                    logger.error(f"❌ 从设备 {device_id} 获取数据失败: {e}")
                    logger.error(f"详细错误信息: {traceback.format_exc()}")
            
            logger.info(f"⏰ 数据收集循环本轮结束，等待 {update_interval} 秒...")
            
            # 保持历史记录在合理范围内（最近1小时）
            cutoff_time = current_time - timedelta(hours=1)
            data_history = [
                entry for entry in data_history 
                if datetime.fromisoformat(entry['timestamp']) > cutoff_time
            ]
            
            # 如果有新数据，更新缓存
            if new_data_received:
                refresh_data_cache()
                retry_count = 0  # 重置重试计数
            else:
                retry_count += 1
                logger.warning(f"没有收到新数据 (重试 {retry_count}/{max_retries})")
                
                # 如果连续多次没有数据，记录错误
                if retry_count >= max_retries:
                    logger.error(f"连续 {max_retries} 次未收到数据，可能存在连接问题")
                    retry_count = 0
            
            # 检查缓存过期
            if data_cache['cache_time'] and (current_time - data_cache['cache_time']).total_seconds() > cache_ttl * 60:
                logger.info("数据缓存已过期，将在下次请求时刷新")
                data_cache['cache_time'] = None  # 标记为需要刷新
            
            time.sleep(update_interval)
            
        except Exception as e:
            logger.error(f"数据收集循环错误: {e}")
            time.sleep(max(1, update_interval / 2))  # 错误后稍微延迟再重试

def refresh_data_cache():
    """刷新数据缓存"""
    global data_cache, latest_data
    
    try:
        response_data = {
            'timestamp': datetime.now().isoformat(),
            'devices': latest_data,
            'total_devices': len(device_connectors),
            'active_devices': len(latest_data)
        }
        
        data_cache['current_data'] = response_data
        data_cache['cache_time'] = datetime.now()
        
        logger.debug("数据缓存已刷新")
    except Exception as e:
        logger.error(f"刷新数据缓存失败: {e}")
    
def get_system_stats():
    """获取系统状态统计"""
    global api_response_times
    
    # 计算API响应时间统计
    api_stats = {}
    if api_response_times:
        # 按端点分组
        endpoints = {}
        for record in api_response_times:
            endpoint = record['endpoint']
            if endpoint not in endpoints:
                endpoints[endpoint] = []
            endpoints[endpoint].append(record['time_ms'])
        
        # 计算每个端点的统计数据
        for endpoint, times in endpoints.items():
            api_stats[endpoint] = {
                'count': len(times),
                'avg_ms': sum(times) / len(times),
                'min_ms': min(times),
                'max_ms': max(times)
            }
    
    return {
        'uptime': time.time() - startup_time,
        'devices': {
            'total': len(device_connectors),
            'active': len(latest_data)
        },
        'api_performance': api_stats,
        'data_collection': {
            'running': is_running,
            'history_entries': len(data_history)
        },
        'memory_usage': {
            'data_history_size': len(data_history),
            'latest_data_size': len(latest_data)
        },
        'cache': {
            'last_updated': data_cache['cache_time'].isoformat() if data_cache['cache_time'] else None
        },
        'auto_control': auto_control_service.get_status()
    }

# API 路由

@app.route('/')
def index():
    """主页面"""
    try:
        # 直接返回项目根目录下的index.html文件
        return send_file('index.html')
    except Exception as e:
        logger.error(f"返回主页面时出错: {e}")
        return f"<h1>错误</h1><p>无法加载主页: {str(e)}</p>", 500

@app.route('/api/status')
@monitor_performance
def api_status():
    """API状态检查"""
    return jsonify({
        'status': 'running',
        'timestamp': datetime.now().isoformat(),
        'devices_count': len(device_connectors),
        'data_collection_active': is_running,
        'latest_data_devices': list(latest_data.keys())
    })

@app.route('/api/health')
def health_check():
    """健康检查端点 - 用于监控系统健康状态"""
    try:
        # 检查关键系统组件
        system_healthy = is_running and len(device_connectors) > 0
        
        # 检查数据是否正常更新 (如果最近15分钟没有更新，视为不健康)
        data_fresh = True
        if data_cache['cache_time']:
            time_since_update = (datetime.now() - data_cache['cache_time']).total_seconds()
            data_fresh = time_since_update < 900  # 15分钟
        
        is_healthy = system_healthy and data_fresh
        
        response_data = {
            'status': 'healthy' if is_healthy else 'unhealthy',
            'timestamp': datetime.now().isoformat(),
            'checks': {
                'system_running': is_running,
                'devices_available': len(device_connectors) > 0,
                'data_collection_active': is_running,
                'data_fresh': data_fresh
            }
        }
        
        status_code = 200 if is_healthy else 503  # 如果不健康，返回503 Service Unavailable
        return jsonify(response_data), status_code
    except Exception as e:
        logger.error(f"健康检查失败: {e}")
        return jsonify({
            'status': 'unhealthy',
            'error': str(e),
            'timestamp': datetime.now().isoformat()
        }), 503

@app.route('/api/current-data')
@monitor_performance
def current_data():
    """获取当前所有设备数据 - 优先返回物模型格式"""
    try:
        # 检查缓存是否有效
        now = datetime.now()
        cache_valid = (
            data_cache['current_data'] is not None and 
            data_cache['cache_time'] is not None and
            (now - data_cache['cache_time']).total_seconds() < 2  # 2秒内的缓存有效
        )
        
        # 创建物模型格式的响应数据
        property_model_response = create_property_model_response()
        
        # 如果物模型数据可用，则优先返回物模型格式
        if property_model_response:
            # 更新缓存
            data_cache['current_data'] = property_model_response
            data_cache['cache_time'] = now
            
            logger.debug("返回物模型格式数据")
            return jsonify(property_model_response)
        
        # 如果物模型数据不可用，则返回传统格式
        if cache_valid:
            logger.debug("使用缓存的传统格式数据响应")
            return jsonify(data_cache['current_data'])
        
        # 生成传统格式响应
        traditional_response = {
            'timestamp': now.isoformat(),
            'devices': latest_data,
            'total_devices': len(device_connectors),
            'active_devices': len(latest_data)
        }
        
        # 更新缓存
        data_cache['current_data'] = traditional_response
        data_cache['cache_time'] = now
        
        logger.debug("返回传统格式数据")
        return jsonify(traditional_response)
    except Exception as e:
        logger.error(f"获取当前数据失败: {e}")
        # 如果有缓存数据，在出错时返回缓存
        if data_cache['current_data']:
            logger.warning("出错时返回缓存数据")
            return jsonify({
                **data_cache['current_data'],
                'is_cached': True,
                'cache_time': data_cache['cache_time'].isoformat() if data_cache['cache_time'] else None,
                'error': str(e)
            })
        return jsonify({'error': str(e)}), 500

@app.route('/api/device/<device_id>')
@monitor_performance
def device_data(device_id):
    """获取特定设备数据"""
    if device_id in latest_data:
        return jsonify({
            'device_id': device_id,
            'data': latest_data[device_id],
            'timestamp': datetime.now().isoformat()
        })
    else:
        return jsonify({'error': f'设备 {device_id} 未找到'}), 404

@app.route('/api/history')
@monitor_performance
def get_history():
    """获取历史数据"""
    try:
        # 获取查询参数
        device_id = request.args.get('device_id')
        limit = int(request.args.get('limit', 100))
        
        filtered_history = data_history
        
        # 按设备过滤
        if device_id:
            filtered_history = [
                entry for entry in data_history 
                if entry['device_id'] == device_id
            ]
        
        # 限制返回数量
        filtered_history = filtered_history[-limit:]
        
        return jsonify({
            'history': filtered_history,
            'total_entries': len(filtered_history),
            'query': {
                'device_id': device_id,
                'limit': limit
            }
        })
    except Exception as e:
        logger.error(f"获取历史数据失败: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/stats')
@monitor_performance
def get_stats():
    """获取系统统计信息"""
    try:
        return jsonify(get_system_stats())
    except Exception as e:
        logger.error(f"获取系统统计信息失败: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/adjust-bed', methods=['POST'])
@monitor_performance
def adjust_bed():
    """调整床板位置"""
    try:
        start_time = time.time()
        data = request.get_json()
        
        if not data:
            return jsonify({'error': '请求数据为空'}), 400
        
        device_id = data.get('device_id')
        angle = data.get('angle')
        
        # 验证参数
        if not device_id:
            return jsonify({'error': '设备ID不能为空'}), 400
        
        if device_id not in device_connectors:
            return jsonify({'error': f'设备 {device_id} 未找到'}), 404
        
        # 验证床板数据
        validation_errors = validate_bed_data(data)
        if validation_errors:
            return jsonify({'error': '参数验证失败', 'details': validation_errors}), 400
        
        # 发送控制指令
        connector = device_connectors[device_id]
        
        # 添加请求追踪ID
        request_id = f"req_{int(time.time())}_{hash(str(data))}"
        logger.info(f"床板控制请求开始 [{request_id}]: 设备={device_id}, 角度={angle}, 速度={data.get('speed_level', 1)}")
        
        # 检查是否为改进的阿里云IoT设备
        if isinstance(connector, ImprovedAliyunIoTConnector):
            # 使用阿里云IoT的控制方法
            result = connector.control_device(
                angle=angle,
                speed_level=data.get('speed_level', 1)
            )
        else:
            # 使用普通设备的命令方法
            command = f"SET_ANGLE:{angle}"
            result = connector.send_command(command)
        
        execution_time = time.time() - start_time
        
        if result and result.get('success', False):
            logger.info(f"床板控制请求成功 [{request_id}], 耗时: {execution_time:.2f}秒")
            
            # 添加缓存刷新标记，使下次API请求获取最新数据
            data_cache['cache_time'] = None
            
            return jsonify({
                'status': 'success',
                'message': '指令下发成功',
                'device_id': device_id,
                'angle': angle,
                'speed_level': data.get('speed_level', 1),
                'result': result,
                'request_id': request_id,
                'execution_time': execution_time,
                'timestamp': datetime.now().isoformat()
            })
        else:
            error_msg = result.get('error', '指令发送失败') if result else '指令发送失败'
            logger.error(f"床板控制请求失败 [{request_id}]: {error_msg}, 耗时: {execution_time:.2f}秒")
            return jsonify({
                'status': 'error',
                'error': error_msg,
                'request_id': request_id,
                'execution_time': execution_time,
                'timestamp': datetime.now().isoformat()
            }), 500
            
    except Exception as e:
        logger.error(f"床板控制请求异常: {str(e)}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/auto-control/status', methods=['GET'])
@monitor_performance
def auto_control_status():
    """获取自动控制服务状态"""
    try:
        status = auto_control_service.get_status()
        return jsonify({
            'status': 'success',
            'data': status,
            'timestamp': datetime.now().isoformat()
        })
    except Exception as e:
        logger.error(f"获取自动控制状态失败: {e}")
        return jsonify({
            'status': 'error',
            'error': str(e),
            'timestamp': datetime.now().isoformat()
        }), 500

@app.route('/api/auto-control/enable', methods=['POST'])
@monitor_performance
def enable_auto_control():
    """启用自动控制服务"""
    try:
        if not auto_control_service.settings['ENABLED']:
            auto_control_service.update_settings({'ENABLED': True})
            logger.info("自动控制服务已启用")
            return jsonify({
                'status': 'success',
                'message': '自动控制服务已启用',
                'timestamp': datetime.now().isoformat()
            })
        else:
            logger.info("自动控制服务已经是启用状态")
            return jsonify({
                'status': 'success',
                'message': '自动控制服务已经是启用状态',
                'timestamp': datetime.now().isoformat()
            })
    except Exception as e:
        logger.error(f"启用自动控制服务失败: {e}")
        return jsonify({
            'status': 'error',
            'error': str(e),
            'timestamp': datetime.now().isoformat()
        }), 500

@app.route('/api/auto-control/disable', methods=['POST'])
@monitor_performance
def disable_auto_control():
    """禁用自动控制服务"""
    try:
        if auto_control_service.settings['ENABLED']:
            auto_control_service.update_settings({'ENABLED': False})
            logger.info("自动控制服务已禁用")
            return jsonify({
                'status': 'success',
                'message': '自动控制服务已禁用',
                'timestamp': datetime.now().isoformat()
            })
        else:
            logger.info("自动控制服务已经是禁用状态")
            return jsonify({
                'status': 'success',
                'message': '自动控制服务已经是禁用状态',
                'timestamp': datetime.now().isoformat()
            })
    except Exception as e:
        logger.error(f"禁用自动控制服务失败: {e}")
        return jsonify({
            'status': 'error',
            'error': str(e),
            'timestamp': datetime.now().isoformat()
        }), 500

@app.route('/api/test-data')
@monitor_performance
def test_data():
    """获取测试数据（用于前端调试）- 物模型格式"""
    try:
        import random
        from datetime import datetime

        # 生成随机测试数据 - 符合物模型结构
        current_time = datetime.now().isoformat()
        
        # 创建物模型结构数据
        property_infos = [
            {"Identifier": "radar_heartrate", "Value": str(random.randint(60, 100)), "DataType": "int"},
            {"Identifier": "radar_breath", "Value": str(random.randint(12, 25)), "DataType": "int"},
            {"Identifier": "temp", "Value": str(round(random.uniform(36.0, 37.5), 1)), "DataType": "int"},
            {"Identifier": "humidity", "Value": str(random.randint(40, 65)), "DataType": "int"},
            {"Identifier": "brightness", "Value": str(random.randint(100, 800)), "DataType": "int"},
            {"Identifier": "dB", "Value": str(random.randint(30, 60)), "DataType": "int"},
            {"Identifier": "sleep_state", "Value": str(random.randint(0, 3)), "DataType": "int"},
            {"Identifier": "radar_sleep_score", "Value": str(random.randint(60, 95)), "DataType": "int"},
            {"Identifier": "sleepflag", "Value": str(random.randint(0, 1)), "DataType": "int"},
            {"Identifier": "body_movement", "Value": str(random.randint(0, 10)), "DataType": "int"},
            {"Identifier": "radar_body_exist", "Value": "1", "DataType": "int"},
            {"Identifier": "LightSwitch", "Value": random.choice(["true", "false"]), "DataType": "bool"},
            {"Identifier": "sitting_up", "Value": str(random.randint(0, 1)), "DataType": "int"},
            {"Identifier": "sleeping", "Value": str(random.randint(0, 1)), "DataType": "int"},
            {"Identifier": "turn_over", "Value": str(random.randint(0, 1)), "DataType": "int"},
            {"Identifier": "pose", "Value": str(random.randint(0, 3)), "DataType": "int"},
            {"Identifier": "servoangle", "Value": str(random.randint(0, 90)), "DataType": "int"},
            {"Identifier": "servospeed", "Value": str(random.randint(1, 5)), "DataType": "int"},
            {"Identifier": "heat", "Value": str(random.randint(0, 3)), "DataType": "int"}
        ]
        
        # 物模型数据结构
        test_data = {
            "RequestId": "8B19E13D-1A95-4C91-8D65-6A59538B293F",
            "Success": True,
            "Data": {
                "List": {
                    "PropertyStatusInfo": property_infos
                },
                "NextValid": False,
                "NextTime": 0
            },
            "Code": "Success"
        }
        
        # 为了兼容旧的前端结构，也提供传统格式
        traditional_data = {
            'timestamp': current_time,
            'active_devices': 2,
            'total_devices': 2,
            'devices': {
                'device1': {
                    'device': 'Spark',
                    'heart_rate': random.randint(60, 100),
                    'heart_rate_display': f"{random.randint(60, 100)} bpm",
                    'breath_rate': random.randint(12, 25),
                    'breath_rate_display': f"{random.randint(12, 25)} /min",
                    'temperature': round(random.uniform(36.0, 37.5), 1),
                    'temperature_display': f"{round(random.uniform(36.0, 37.5), 1)}°C",
                    'humidity': random.randint(40, 65),
                    'humidity_display': f"{random.randint(40, 65)}%",
                    'timestamp': current_time,
                },
                'device2': {
                    'device': 'monitor',
                    'timestamp': current_time
                }
            }
        }
        
        # 将传统数据格式作为备用字段加入到物模型结构中
        test_data['traditional_format'] = traditional_data

        app.logger.info(f"生成测试数据: {test_data}")
        return jsonify(test_data)
    except Exception as e:
        app.logger.error(f"生成测试数据失败: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/auto-control/settings', methods=['GET', 'POST'])
@monitor_performance
def auto_control_settings():
    """获取或更新自动控制服务设置"""
    try:
        if request.method == 'GET':
            return jsonify({
                'status': 'success',
                'data': auto_control_service.settings,
                'timestamp': datetime.now().isoformat()
            })
        else:  # POST
            new_settings = request.get_json()
            if not new_settings:
                return jsonify({
                    'status': 'error',
                    'error': '无效的设置数据',
                    'timestamp': datetime.now().isoformat()
                }), 400
                
            success = auto_control_service.update_settings(new_settings)
            if success:
                logger.info(f"自动控制服务设置已更新: {new_settings}")
                return jsonify({
                    'status': 'success',
                    'message': '设置已更新',
                    'data': auto_control_service.settings,
                    'timestamp': datetime.now().isoformat()
                })
            else:
                logger.warning(f"更新自动控制服务设置失败: {new_settings}")
                return jsonify({
                    'status': 'error',
                    'error': '更新设置失败',
                    'timestamp': datetime.now().isoformat()
                }), 400
    except Exception as e:
        logger.error(f"自动控制服务设置操作失败: {e}")
        return jsonify({
            'status': 'error',
            'error': str(e),
            'timestamp': datetime.now().isoformat()
        }), 500

@app.route('/api/db-status')
@monitor_performance
def database_status():
    """获取数据库状态和统计信息"""
    try:
        # 验证数据库
        db_status = verify_database()
        
        # 获取数据库统计信息
        stats = {}
        try:
            with closing(sqlite3.connect(DB_PATH)) as conn:
                cursor = conn.cursor()
                
                # 总记录数
                cursor.execute("SELECT COUNT(*) FROM property_model_data")
                stats['total_records'] = cursor.fetchone()[0]
                
                # 每种标识符的记录数
                cursor.execute("""
                    SELECT identifier, COUNT(*) as count 
                    FROM property_model_data 
                    GROUP BY identifier
                """)
                stats['records_by_identifier'] = {row[0]: row[1] for row in cursor.fetchall()}
                
                # 最早和最晚的记录时间
                cursor.execute("SELECT MIN(timestamp), MAX(timestamp) FROM property_model_data")
                min_max = cursor.fetchone()
                stats['earliest_record'] = min_max[0]
                stats['latest_record'] = min_max[1]
                
                # 数据库文件大小
                if os.path.exists(DB_PATH):
                    stats['file_size_bytes'] = os.path.getsize(DB_PATH)
                    stats['file_size_mb'] = round(stats['file_size_bytes'] / (1024 * 1024), 2)
                
        except Exception as e:
            stats['error'] = str(e)
            
        return jsonify({
            'status': db_status['status'],
            'details': db_status,
            'statistics': stats,
            'timestamp': datetime.now().isoformat()
        })
    except Exception as e:
        logger.error(f"获取数据库状态失败: {e}")
        return jsonify({
            'status': '异常',
            'error': str(e),
            'timestamp': datetime.now().isoformat()
        }), 500

# HTML模板已移除，现在使用index.html文件

# 保存物模型数据到数据库
def save_property_model_data(property_data_list):
    """
    保存物模型数据到SQLite数据库
    只处理空值，直接存数据库
    """
    try:
        current_time = datetime.now().isoformat()
        
        with closing(sqlite3.connect(DB_PATH)) as conn:
            cursor = conn.cursor()
            
            for item in property_data_list:
                identifier = item.get('Identifier')
                value = item.get('Value')
                
                # 只处理空值
                if value is None or value == '':
                    value = '0'
                
                # 尝试转换为数值
                try:
                    numeric_value = float(value)
                except:
                    numeric_value = 0.0
                
                # 直接保存到数据库
                cursor.execute(
                    '''INSERT INTO property_model_data 
                       (timestamp, identifier, value, numeric_value, data_type, name, time, is_valid, data_quality) 
                       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)''',
                    (current_time, 
                     identifier, 
                     value,
                     numeric_value,
                     item.get('DataType', ''),
                     item.get('Name', ''),
                     item.get('Time', ''),
                     1,
                     100)
                )
            
            conn.commit()
            return True
    except Exception as e:
        logger.error(f"保存物模型数据失败: {e}")
        return False

# 从数据库获取最新的物模型数据
def get_latest_property_model_data():
    """获取数据库中最新的物模型数据，优先返回高质量有效数据"""
    try:
        with closing(sqlite3.connect(DB_PATH)) as conn:
            # 设置行工厂为字典，方便访问字段
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            result = {}
            
            # 对于每个关心的字段，获取最新的高质量有效记录
            for field in ['radar_heartrate', 'radar_breath', 'temp', 'humidity']:
                cursor.execute(
                    '''SELECT value, numeric_value, data_type, name, time, timestamp, data_quality, id
                       FROM property_model_data
                       WHERE identifier = ? AND is_valid = 1
                       ORDER BY id DESC
                       LIMIT 10''',  # 获取最近10条记录，以便选择最好的
                    (field,)
                )
                rows = cursor.fetchall()
                
                # 如果有记录，尝试选择最好的一条
                if rows:
                    best_row = None
                    best_quality = 0
                    
                    for row in rows:
                        row_dict = dict(row)
                        # 选择质量最高的记录
                        if row_dict['data_quality'] > best_quality:
                            best_row = row_dict
                            best_quality = row_dict['data_quality']
                    
                    # 如果找到合适的记录
                    if best_row:
                        result[field] = {
                            'value': best_row['value'],
                            'numeric_value': best_row['numeric_value'],
                            'data_type': best_row['data_type'],
                            'name': best_row['name'],
                            'time': best_row['time'],
                            'timestamp': best_row['timestamp'],
                            'data_quality': best_row['data_quality'],
                            'id': best_row['id']
                        }
                        logger.debug(f"✅ 获取{field}最佳数据: value={best_row['value']}, quality={best_row['data_quality']}")
                
                # 如果没有找到记录，记录警告日志
                if field not in result:
                    logger.warning(f"⚠️ 数据库中没有找到{field}的有效数据")
                    
            # 记录结果摘要
            if result:
                field_values = [f"{field}={data.get('value', 'N/A')}" for field, data in result.items()]
                logger.info(f"📊 从数据库获取的数据: {', '.join(field_values)}")
            else:
                logger.warning("⚠️ 数据库中没有任何有效物模型数据")
                
            return result
    except Exception as e:
        logger.error(f"❌ 获取物模型数据失败: {e}")
        logger.error(traceback.format_exc())
        return {}

# 清理旧数据（保留最近24小时数据）
def cleanup_old_data():
    """清理24小时前的数据"""
    try:
        with closing(sqlite3.connect(DB_PATH)) as conn:
            cursor = conn.cursor()
            one_day_ago = (datetime.now() - timedelta(days=1)).isoformat()
            cursor.execute(
                "DELETE FROM property_model_data WHERE timestamp < ?",
                (one_day_ago,)
            )
            conn.commit()
            deleted_count = cursor.rowcount
            if deleted_count > 0:
                logger.info(f"🧹 已清理 {deleted_count} 条旧数据")
    except Exception as e:
        logger.error(f"❌ 清理旧数据失败: {e}")
        logger.error(traceback.format_exc())

# 创建物模型格式的响应数据
def create_property_model_response():
    """
    创建符合物模型数据格式的API响应
    优先使用数据库中存储的物模型数据
    如果数据库没有数据，则使用全局缓存
    """
    try:
        # 从数据库获取最新的物模型数据
        latest_db_data = get_latest_property_model_data()
        
        if not latest_db_data:
            # 数据库中没有数据，检查全局缓存
            if not any(data_cache['property_model_data'].values()):
                logger.warning("⚠️ 没有可用的物模型数据")
                return None
            
            # 使用缓存数据
            property_data = []
            for identifier, data in data_cache['property_model_data'].items():
                if data and data.get('value') is not None:
                    property_data.append({
                        'Identifier': identifier,
                        'Value': data.get('value'),
                        'DataType': data.get('data_type', 'int'),
                        'Name': data.get('name', identifier),
                        'Time': data.get('time', str(int(time.time() * 1000)))
                    })
            
            data_source = "内存缓存"
            update_time = data_cache['last_update_time'] or datetime.now().isoformat()
        else:
            # 使用数据库数据
            property_data = []
            for identifier, data in latest_db_data.items():
                property_data.append({
                    'Identifier': identifier,
                    'Value': data.get('value'),
                    'DataType': data.get('data_type', 'int'),
                    'Name': data.get('name', identifier),
                    'Time': data.get('time', str(int(time.time() * 1000)))
                })
            
            data_source = "数据库"
            update_time = max(item.get('timestamp', '') for item in latest_db_data.values())
        
        # 构建完整的物模型响应
        response = {
            'RequestId': f"{int(time.time() * 1000)}-{id(property_data)}",
            'Success': True,
            'Data': {
                'List': {
                    'PropertyStatusInfo': property_data
                },
                'NextValid': False,
                'NextTime': 0
            },
            'Code': 'Success',
            'metadata': {
                'source': data_source,
                'timestamp': update_time,
                'count': len(property_data)
            }
        }
        
        # 同时添加传统格式作为备用，确保数值转换安全
        try:
            response['traditional_format'] = {
                'timestamp': update_time,
                'devices': {
                    'device1': {
                        'device': 'Spark',
                        'heart_rate': int(float(next((item['Value'] for item in property_data if item['Identifier'] == 'radar_heartrate'), "0"))),
                        'heart_rate_display': f"{int(float(next((item['Value'] for item in property_data if item['Identifier'] == 'radar_heartrate'), '0')))} bpm",
                        'breath_rate': int(float(next((item['Value'] for item in property_data if item['Identifier'] == 'radar_breath'), "0"))),
                        'breath_rate_display': f"{int(float(next((item['Value'] for item in property_data if item['Identifier'] == 'radar_breath'), '0')))} /min",
                        'temperature': float(next((item['Value'] for item in property_data if item['Identifier'] == 'temp'), "0")),
                        'temperature_display': f"{float(next((item['Value'] for item in property_data if item['Identifier'] == 'temp'), '0'))}°C",
                        'humidity': int(float(next((item['Value'] for item in property_data if item['Identifier'] == 'humidity'), "0"))),
                        'humidity_display': f"{int(float(next((item['Value'] for item in property_data if item['Identifier'] == 'humidity'), '0')))}%",
                        'timestamp': update_time
                    }
                }
            }
        except Exception as e:
            logger.error(f"创建传统格式响应失败: {e}")
            response['traditional_format'] = {
                'timestamp': update_time,
                'devices': {
                    'device1': {
                        'device': 'Spark',
                        'heart_rate': 0,
                        'heart_rate_display': "0 bpm",
                        'breath_rate': 0,
                        'breath_rate_display': "0 /min",
                        'temperature': 0,
                        'temperature_display': "0°C",
                        'humidity': 0,
                        'humidity_display': "0%",
                        'timestamp': update_time,
                        'error': str(e)
                    }
                }
            }
        
        logger.info(f"✅ 创建物模型响应成功: {len(property_data)}个属性, 来源: {data_source}")
        return response
    
    except Exception as e:
        logger.error(f"❌ 创建物模型响应失败: {e}")
        logger.error(traceback.format_exc())
        return None

# 验证数据库状态
def verify_database():
    """检查数据库是否可用并能正常读写"""
    try:
        # 检查数据库文件是否存在
        db_exists = os.path.exists(DB_PATH)
        
        # 尝试连接数据库
        with closing(sqlite3.connect(DB_PATH)) as conn:
            cursor = conn.cursor()
            
            # 检查表是否存在
            cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='property_model_data'")
            table_exists = cursor.fetchone() is not None
            
            # 测试写入
            if table_exists:
                try:
                    test_time = datetime.now().isoformat()
                    cursor.execute(
                        "INSERT INTO property_model_data (timestamp, identifier, value, numeric_value, is_valid) VALUES (?, ?, ?, ?, ?)",
                        (test_time, "test_record", "test_value", 0.0, 0)
                    )
                    conn.commit()
                    
                    # 检查是否写入成功
                    cursor.execute("SELECT id FROM property_model_data WHERE identifier = 'test_record' AND timestamp = ?", (test_time,))
                    write_success = cursor.fetchone() is not None
                    
                    # 删除测试记录
                    cursor.execute("DELETE FROM property_model_data WHERE identifier = 'test_record'")
                    conn.commit()
                except Exception as e:
                    write_success = False
                    logger.error(f"数据库写入测试失败: {e}")
            else:
                write_success = False
                
            # 返回状态信息
            status = {
                "db_exists": db_exists,
                "table_exists": table_exists,
                "write_success": write_success,
                "status": "正常" if (db_exists and table_exists and write_success) else "异常"
            }
            
            logger.info(f"数据库状态: {'✅正常' if status['status'] == '正常' else '❌异常'}, "
                       f"文件存在: {'✓' if status['db_exists'] else '✗'}, "
                       f"表存在: {'✓' if status['table_exists'] else '✗'}, "
                       f"写入测试: {'✓' if status['write_success'] else '✗'}")
            
            return status
    except Exception as e:
        logger.error(f"数据库验证失败: {e}")
        return {
            "db_exists": os.path.exists(DB_PATH),
            "table_exists": False,
            "write_success": False,
            "status": "异常",
            "error": str(e)
        }

def main():
    """主函数"""
    global is_running
    
    logger.info("🛏️ 健康床系统启动中...")
    
    try:
        # 初始化数据库
        init_database()
        
        # 验证数据库状态
        db_status = verify_database()
        if db_status['status'] != '正常':
            logger.error("❌ 数据库状态异常！将尝试重新初始化数据库...")
            
            # 尝试删除可能损坏的数据库文件
            try:
                if os.path.exists(DB_PATH):
                    os.remove(DB_PATH)
                    logger.info("✅ 已删除损坏的数据库文件")
            except Exception as e:
                logger.error(f"❌ 无法删除损坏的数据库文件: {e}")
                return
            
            # 重新初始化
            init_database()
            
            # 再次验证
            db_status = verify_database()
            if db_status['status'] != '正常':
                logger.error("❌ 数据库状态仍然异常，无法启动系统！")
                return
            else:
                logger.info("✅ 数据库重新初始化成功，可以正常使用")
        
        # 载入配置
        config = load_config()
        system_config = config.get('system', {})
        
        # 获取更新间隔
        update_interval = system_config.get('update_interval', 5)
        
        # 初始化设备
        devices_count = initialize_devices(config)
        logger.info(f"成功初始化 {devices_count} 个设备")
        
        # 启动数据收集服务
        if not is_running:
            is_running = True
            data_thread = threading.Thread(
                target=data_collection_loop,
                args=(update_interval, config),
                daemon=True
            )
            data_thread.start()
            logger.info(f"数据收集服务已启动，更新间隔: {update_interval}秒")
        
        # 启动自动控制服务
        if not auto_control_service.running:
            auto_control_service.start()
            logger.info("自动控制服务已启动")
        
        logger.info(f"🚀 系统准备完成，启动耗时: {time.time() - startup_time:.2f}秒")
        
        # 启动Flask应用
        host = config.get('api', {}).get('host', '0.0.0.0')
        port = config.get('api', {}).get('port', 5000)
        
        logger.info(f"🌐 Web界面将在 http://{host}:{port} 启动")
        app.run(host=host, port=port, debug=False, threaded=True)
        
    except KeyboardInterrupt:
        logger.info("🛑 接收到中断信号，正在关闭...")
    except Exception as e:
        logger.error(f"❌ 启动失败: {e}")
    finally:
        # 停止数据收集
        is_running = False
        
        # 停止自动控制服务
        auto_control_service.stop()
        
        logger.info("� 系统已关闭")

if __name__ == '__main__':
    main()
